﻿using System.Data;
using System.Reflection;

namespace U8DllPack.Controller
{
    public class ModelHelper
    {
        /// <summary>
        /// 将SqlDataReader转换为Model实体
        /// </summary>
        /// <typeparam name="T">实例类名</typeparam>
        /// <param name="dr">Reader对象</param>
        /// <returns>实体对象</returns>
        public static T? ReaderToModel<T>(IDataReader dr)
        {
            try
            {
                using (dr)
                {
                    if (dr.Read())
                    {
                        Type? modelType = typeof(T);
                        T model = Activator.CreateInstance<T>();
                        for (int i = 0; i < dr.FieldCount; i++)
                        {
                            if (!IsNullOrDbNull(dr[i]))
                            {
                                PropertyInfo? pi = GetPropertyInfo(modelType.GetProperties(), dr.GetName(i));
                                if (pi == null) continue;
                                if (pi.CanWrite) pi.SetValue(model, HackType(dr[i], pi.PropertyType), null);
                            }
                        }
                        return model;
                    }
                }
                return default;
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 将DataRow转换为Model实体
        /// </summary>
        /// <typeparam name="T">实例类名</typeparam>
        /// <param name="dr">DataRow对象</param>
        /// <returns></returns>
        public static T? DataRowToModel<T>(DataRow dr)
        {
            try
            {
                if (dr != null)
                {
                    Type? modelType = typeof(T);
                    T model = Activator.CreateInstance<T>();
                    foreach (DataColumn col in dr.Table.Columns)
                    {
                        if (!IsNullOrDbNull(dr[col.ColumnName]))
                        {
                            PropertyInfo? pi = GetPropertyInfo(modelType.GetProperties(), col.ColumnName);
                            if (pi == null) continue;
                            if (pi.CanWrite) pi.SetValue(model, HackType(dr[col.ColumnName], pi.PropertyType), null);
                        }
                    }
                    return model;
                }
                return default;
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 将SqlDataReader转换为List实体
        /// </summary>
        /// <typeparam name="T">实例类名</typeparam>
        /// <param name="dr">Reader对象</param>
        /// <returns>列表实体</returns>
        public static List<T>? ReaderToListModel<T>(IDataReader dr)
        {
            try
            {
                using (dr)
                {
                    List<T>? list_model = null;
                    while (dr.Read())
                    {
                        Type modelType = typeof(T);
                        T model = Activator.CreateInstance<T>();
                        for (int i = 0; i < dr.FieldCount; i++)
                        {
                            if (!IsNullOrDbNull(dr[i]))
                            {
                                PropertyInfo? pi = GetPropertyInfo(modelType.GetProperties(), dr.GetName(i));
                                if (pi == null) continue;
                                if (pi.CanWrite) pi.SetValue(model, HackType(dr[i], pi.PropertyType), null);
                            }
                        }
                        if (list_model == null)
                        {
                            list_model = new List<T>();
                        }
                        list_model.Add(model);
                    }
                    return list_model;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        ///  对可空类型进行判断.
        /// </summary> 
        private static object? HackType(object value, Type conversionType)
        {
            if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null)
                {
                    return null;
                }
                System.ComponentModel.NullableConverter nullAbleConverter = new(conversionType);
                conversionType = nullAbleConverter.UnderlyingType;
            }
            return Convert.ChangeType(value, conversionType);
        }

        /// <summary>
        ///  判断字段值是否为NUll
        /// </summary>
        /// <param name="obj">字段对象</param>
        /// <returns></returns>
        private static bool IsNullOrDbNull(object? obj)
        {
            return Convert.IsDBNull(obj) || Convert.ToString(obj).IsNullOrWhiteSpace();
        }

        /// <summary>
        /// 获取指定名称的实例属性对象
        /// </summary>
        /// <param name="PropInfos">对象属性数组</param>
        /// <param name="PropertyName">属性名称</param>
        /// <returns></returns>
        public static PropertyInfo? GetPropertyInfo(PropertyInfo[] PropInfos, string PropertyName)
        {
            PropertyInfo? propertyInfo = null;
            foreach (var pi in PropInfos)
            {
                if (pi.Name.ToLower().Equals(PropertyName.ToLower()))
                {
                    propertyInfo = pi;
                    break;
                }
            }
            return propertyInfo;
        }


    }
}
